﻿Imports Microsoft.TeamFoundation.Client
Imports Microsoft.TeamFoundation.WorkItemTracking.Client
Imports System.Threading

Public Class TFSController(Of TView As {Form, ITFSLoaderView})

    Private m_View As TView

    Public Sub New(ByVal View As TView)
        m_View = View
    End Sub

#Region " TFS Connections "

    Dim WorkItemStoreCache As New Dictionary(Of String, WorkItemStore)

    Public Function GetServers() As ArrayList
        Dim Servers As New ArrayList
        Dim serverNames As String() = RegisteredServers.GetServerNames
        Servers.AddRange(serverNames)
        Return Servers
    End Function

    Public Function GetTeamFoundationServer(ByVal ServerName As String) As TeamFoundationServer
        Return TeamFoundationServerFactory.GetServer(ServerName)
    End Function

    Public Function GetWorkItemStore(ByVal ServerName As String) As WorkItemStore
        SyncLock WorkItemStoreCache
            If Not WorkItemStoreCache.ContainsKey(ServerName) Then
                Dim TFS As TeamFoundationServer = GetTeamFoundationServer(ServerName)
                Dim WIT As WorkItemStore = DirectCast(TFS.GetService(GetType(WorkItemStore)), WorkItemStore)
                WorkItemStoreCache.Add(ServerName, WIT)
            End If
        End SyncLock
        Return WorkItemStoreCache(ServerName)
    End Function

#End Region

#Region " Load Servers "

    Private Delegate Sub ServerDelegate(ByVal Server As TeamFoundationServer)

    Public Sub LoadServersAsync()
        System.Threading.ThreadPool.QueueUserWorkItem(AddressOf LoadServersWaitCallback)
    End Sub

    Private Sub LoadServersWaitCallback(ByVal state As Object)
        LoadServers()
    End Sub

    Public Sub LoadServers()
        Dim serverNames As String() = RegisteredServers.GetServerNames
        For Each serverName As String In serverNames
            Dim TFS As TeamFoundationServer = GetTeamFoundationServer(serverName)
            If Me.m_View.InvokeRequired Then
                Me.m_View.Invoke(New ServerDelegate(AddressOf m_View.OnServerLoaded), TFS)
            Else
                m_View.OnServerLoaded(TFS)
            End If
        Next
    End Sub

    Public Function GetServerNames() As String()
        Return RegisteredServers.GetServerNames
    End Function

#End Region

#Region " Load Start / End "

    Private Delegate Sub LoadingDelegate(ByVal Type As TFSPoulationType)

    Private Sub LoadBegin(ByVal Type As TFSPoulationType)
        If Me.m_View.InvokeRequired Then
            Me.m_View.Invoke(New LoadingDelegate(AddressOf Me.m_View.OnLoadBegin), Type)
            Thread.Sleep(100)
        Else
            Me.m_View.OnLoadBegin(Type)
            Thread.Sleep(100)
        End If
    End Sub

    Private Sub LoadEnd(ByVal Type As TFSPoulationType)
        If Me.m_View.InvokeRequired Then
            Me.m_View.Invoke(New LoadingDelegate(AddressOf Me.m_View.OnLoadEnd), Type)
            Thread.Sleep(100)
        Else
            Me.m_View.OnLoadEnd(Type)
            Thread.Sleep(100)
        End If
    End Sub

#End Region

#Region " Load projects "

    Private Delegate Sub ProjectDelegate(ByVal Project As Project)

    Public Sub LoadProjectsAsync(ByVal ServerName As String)
        System.Threading.ThreadPool.QueueUserWorkItem(AddressOf LoadProjectsWaitCallback, ServerName)
    End Sub

    Private Sub LoadProjectsWaitCallback(ByVal state As Object)
        LoadProjects(CStr(state))
    End Sub

    Public Sub LoadProjects(ByVal ServerName As String)
        LoadBegin(TFSPoulationType.Project)
        Dim WIT As WorkItemStore = GetWorkItemStore(ServerName)
        For Each project As Project In WIT.Projects
            If Me.m_View.InvokeRequired Then
                Me.m_View.Invoke(New ProjectDelegate(AddressOf m_View.OnProjectLoaded), project)
                Thread.Sleep(100)
            Else
                m_View.OnProjectLoaded(project)
                Thread.Sleep(100)
            End If
        Next
        LoadEnd(TFSPoulationType.Project)
    End Sub

#End Region

#Region " Load Querys "

    Private Delegate Sub QueryDelegate(ByVal Query As StoredQuery)

    Public Sub LoadQuerysAsync(ByVal ServerName As String, ByVal Project As String)
        Dim x() As String = {ServerName, Project}
        System.Threading.ThreadPool.QueueUserWorkItem(AddressOf LoadQuerysWaitCallback, x)
    End Sub

    Private Sub LoadQuerysWaitCallback(ByVal state As Object)
        Dim x() As String = CType(state, String())
        LoadQuerys(x(0), x(1))
    End Sub

    Public Sub LoadQuerys(ByVal ServerName As String, ByVal Project As String)
        LoadBegin(TFSPoulationType.Query)
        Dim WIT As WorkItemStore = GetWorkItemStore(ServerName)
        Dim objProject As Project = WIT.Projects.Item(Project)
        For Each query As StoredQuery In objProject.StoredQueries
            If Me.m_View.InvokeRequired Then
                Me.m_View.Invoke(New QueryDelegate(AddressOf m_View.OnQueryLoaded), query)
                Thread.Sleep(100)
            Else
                m_View.OnQueryLoaded(query)
                Thread.Sleep(100)
            End If
        Next
        LoadEnd(TFSPoulationType.Query)
    End Sub

#End Region

End Class

Public Enum TFSPoulationType
    Server
    Project
    Query
End Enum